home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Source.bin / Plasma.java < prev    next >
Text File  |  1998-08-21  |  14KB  |  485 lines

  1. package symantec.itools.multimedia;
  2.  
  3.  
  4. import java.awt.Canvas;
  5. import java.awt.Dimension;
  6. import java.awt.Graphics;
  7. import java.awt.Image;
  8. import java.awt.image.IndexColorModel;
  9. import java.awt.image.MemoryImageSource;
  10. import symantec.itools.lang.OS;
  11.  
  12.  
  13. //    05/29/97    RKM    Changed invalidate to repaint
  14. //                    Changed symantec.beans references to java.beans
  15. //                    No Bounding and constraining of the previewMode property (doesn't make sense)
  16. //                    Deprecated getter for booleans, and added is
  17. //  07/16/97    CAR marked fields transient as needed
  18. //  07/16/97    CAR implemented readObject
  19. //  10/17/97    LAB    Added additional checking in removeNotify to avoid NullPointerExceptions
  20. //                    (Addresses Mac Bug #9479).
  21.  
  22. /**
  23.  * Plasma component.
  24.  * Creates an animation of colored amorphous shapes, where colors gradually
  25.  * modulate as shapes merge and separate.
  26.  *
  27.  * @version 1.0, Nov 26, 1996
  28.  * @author Symantec
  29.  */
  30.  
  31. public class Plasma
  32.     extends Canvas
  33.     implements Runnable
  34. {
  35.     int xpoints[];
  36.     int ypoints[];
  37.  
  38.     byte red[];
  39.     byte green[];
  40.     byte blue[];
  41.  
  42.     byte buffer[];
  43.     byte costab[];
  44.     Dimension dim = null;
  45.     transient IndexColorModel cModel = null;
  46.     transient Image img = null;
  47.     byte x1;
  48.     byte x2;
  49.     byte y1;
  50.     byte y2;
  51.     byte x1mod = 6;
  52.     byte x2mod = 8;
  53.     byte y1mod = 6;
  54.     byte y2mod = 4;
  55.  
  56.     boolean keepGoing = true;
  57.     boolean suspended = false;
  58.     boolean stopThread = false;
  59.     boolean Threadstopped = false;
  60.  
  61.     transient Thread displayThread = null;
  62.  
  63.     private boolean previewMode = false;
  64.  
  65.     /**
  66.      * Create default plasma component.
  67.      */
  68.  
  69.     public Plasma()
  70.     {
  71.         super();
  72.  
  73.         xpoints = new int[5];
  74.         ypoints = new int[5];
  75.         red     = new byte[128];
  76.         green   = new byte[128];
  77.         blue    = new byte[128];
  78.  
  79.         dopalette();
  80.  
  81.         cModel = new IndexColorModel(7, 128, red, green, blue);
  82.         costab = new byte[256];
  83.  
  84.         setupcos();
  85.  
  86.         createBuffer();
  87.     }
  88.  
  89.     void createBuffer()
  90.     {
  91.         dim = size();
  92.         buffer = new byte[dim.width * (dim.height + 100)];
  93.         img = null;
  94.     }
  95.  
  96.     /**
  97.      * Tells this component that it has been added to a container.
  98.      * This is a standard Java AWT method which gets called by the AWT when
  99.      * this component is added to a container. Typically, it is used to
  100.      * create this component's peer.
  101.      *
  102.      * It has been overridden here to start the plasma thread.
  103.      *
  104.      * @see #removeNotify
  105.      */
  106.  
  107.     public synchronized void addNotify()
  108.     {
  109.         super.addNotify();
  110.         displayThread = new Thread(this);
  111.         displayThread.setPriority(Thread.MIN_PRIORITY);
  112.         displayThread.start();
  113.     }
  114.  
  115.     /**
  116.      * Tells this component that it is being removed from a container.
  117.      * This is a standard Java AWT method which gets called by the AWT when
  118.      * this component is removed from a container. Typically, it is used to
  119.      * destroy the peers of this component and all its subcomponents.
  120.      *
  121.      * It has been overridden here to stop the plasma thread.
  122.      *
  123.      * @see #addNotify
  124.      */
  125.     public synchronized void removeNotify()
  126.     {
  127.         keepGoing = false;
  128.         stopThread = false;
  129.         if (displayThread != null && displayThread.isAlive())
  130.         {
  131.               displayThread.setPriority(Thread.MAX_PRIORITY);
  132.         }
  133.         if (displayThread != null && displayThread.isAlive())
  134.         {
  135.               displayThread.resume();
  136.         }
  137.         while (displayThread != null &&  displayThread.isAlive())
  138.         {
  139.               try { Thread.sleep(40); } catch(Exception e) { };
  140.         }
  141.         super.removeNotify();
  142.     }
  143.  
  144.     /**
  145.      * Resume plasma animation.
  146.      */
  147.  
  148.     public void startPlasma() {
  149.         suspended = false;
  150.         show();
  151.     }
  152.  
  153.     /**
  154.      * Suspend plasma animation.
  155.      */
  156.     public void stopPlasma() {
  157.         suspended = true;
  158.     }
  159.  
  160.     /**
  161.      * Makes this component visible.
  162.      * This is a standard Java AWT method which gets called to show this
  163.      * component. If this component was invisible due to a previous hide()
  164.      * call it make this component visible again.
  165.      *
  166.      * @see #hide
  167.      */
  168.     public synchronized void show() {
  169.          if (displayThread != null) {
  170.               if (stopThread) {
  171.                     stopThread = false;
  172.               }
  173.               else {
  174.                    displayThread.setPriority(Thread.MAX_PRIORITY);
  175.                     displayThread.resume();
  176.               }
  177.         }
  178.     }
  179.  
  180.     /**
  181.      * Makes this component invisible.
  182.      * This is a standard Java AWT method which gets called to hide
  183.      * this component. A hidden component cannot be seen by the user nor
  184.      * does it take up space in its container, but it does continue to
  185.      * exist.
  186.      *
  187.      * @see #show
  188.      */
  189.     public synchronized void hide() {
  190.          if (!Threadstopped) {
  191.              stopThread = true;
  192.              displayThread.setPriority(Thread.MAX_PRIORITY);
  193.          }
  194.      }
  195.  
  196.     /**
  197.      * Moves and/or resizes this component.
  198.      * This is a standard Java AWT method which gets called to move and/or
  199.      * resize this component. Components that are in containers with layout
  200.      * managers should not call this method, but rely on the layout manager
  201.      * instead.
  202.      *
  203.      * @param x horizontal position in the parent's coordinate space
  204.      * @param y vertical position in the parent's coordinate space
  205.      * @param width the new width
  206.      * @param height the new height
  207.      */
  208.     public synchronized void reshape(int    x,
  209.              int    y,
  210.              int    width,
  211.              int    height)
  212.     {
  213.         super.reshape(x,y,width,height);
  214.         createBuffer();
  215.     }
  216.  
  217.    /**
  218.      * Sets the preview mode flag.  This flag is used by Visual Cafe to
  219.      * determine if this component should be run during design time.
  220.      * @param f new preview mode
  221.      * @see #getPreviewMode
  222.      */
  223.     public void setPreviewMode(boolean f)
  224.     {
  225.         previewMode = f;
  226.         repaint();
  227.     }
  228.  
  229.     /**
  230.      * @deprecated As of JDK version 1.1,
  231.      * replaced by isPreviewMode.
  232.      */
  233.     public boolean getPreviewMode()
  234.     {
  235.         return previewMode;
  236.     }
  237.  
  238.    /**
  239.      * Gets the preview mode flag. This flag is used by Visual Cafe to
  240.      * determine if this component should be run during design time.
  241.      * @see #setPreviewMode
  242.      */
  243.     public boolean isPreviewMode()
  244.     {
  245.         return previewMode;
  246.     }
  247.  
  248.     /**
  249.      * Plasma thread body.  This method is called by the Java virtual
  250.      * machine to when this thread starts.
  251.      */
  252.  
  253.     public void run()
  254.     {
  255.         while (keepGoing) {
  256.  
  257.             if ((!stopThread) && (!suspended) && (previewMode || !java.beans.Beans.isDesignTime()))
  258.                 repaint();
  259.  
  260.                 if (stopThread) {
  261.                     super.hide();
  262.                     Threadstopped = true;
  263.                     displayThread.setPriority(Thread.MIN_PRIORITY);
  264.                     displayThread.suspend();
  265.                     Threadstopped = false;
  266.                     if (keepGoing) {
  267.                         super.show();
  268.                         displayThread.setPriority(Thread.MIN_PRIORITY);
  269.                     }
  270.                 }
  271.                 else {
  272.                     if (keepGoing)
  273.                         try { Thread.sleep(100); } catch(Exception e) { };
  274.                 }
  275.         }
  276.           displayThread = null;
  277.     }
  278.  
  279.     transient private int iteration = 0;
  280.     transient private final int MAX_ITERATION_GC = 25;
  281.  
  282.     /**
  283.      * Paints this component using the given graphics context.
  284.      * This is a standard Java AWT method which typically gets called
  285.      * by the AWT to handle painting this component. It paints this component
  286.      * using the given graphics context. The graphics context clipping region
  287.      * is set to the bounding rectangle of this component and its <0,0>
  288.      * coordinate is this component's top-left corner.
  289.      *
  290.      * @param g the graphics context used for painting
  291.      * @see java.awt.Component#repaint
  292.      * @see #update
  293.      */
  294.     public void paint(Graphics g)
  295.     {
  296.         if (!suspended && (previewMode || !java.beans.Beans.isDesignTime()))
  297.             moveplasma();
  298.  
  299.         //If img is null, we need to create one
  300.         if (img == null)
  301.         {
  302.             drawplasma();
  303.  
  304.             try
  305.             {
  306.                 img = createImage(new MemoryImageSource(dim.width,dim.height,cModel,buffer,0,dim.width));
  307.             }
  308.             catch(Exception e)
  309.             {
  310.             }
  311.         }
  312.  
  313.         if (OS.isMacintosh())
  314.         {
  315.             //Clip the width of the component
  316.             g.clipRect(0, 0, dim.width, dim.height);
  317.         }
  318.  
  319.         //Draw border
  320.         g.drawRect(0, 0, dim.width - 1, dim.height - 1);
  321.  
  322.         //Inset clip 1,1
  323.         g.clipRect(1, 1, dim.width - 2, dim.height - 2);
  324.  
  325.         //Draw plasma image
  326.         if (img != null)
  327.         {
  328.             if (symantec.itools.lang.OS.isMacintosh())
  329.                 g.drawImage(img, 1, 1, null);
  330.             else
  331.                 g.drawImage(img, 1, 1, this);
  332.         }
  333.  
  334.         if (++iteration > MAX_ITERATION_GC) {
  335.             System.gc();
  336.             iteration = 0;
  337.         }
  338.     }
  339.  
  340.     /**
  341.      * Handles redrawing of this component on the screen.
  342.      * This is a standard Java AWT method which gets called by the Java
  343.      * AWT (repaint()) to handle repainting this component on the screen.
  344.      * The graphics context clipping region is set to the bounding rectangle
  345.      * of this component and its <0,0> coordinate is this component's
  346.      * top-left corner.
  347.      * Typically this method paints the background color to clear the
  348.      * component's drawing space, sets graphics context to be the foreground
  349.      * color, and then calls paint() to draw the component.
  350.      *
  351.      * It is overridden here to reduce flicker by eliminating the uneeded
  352.      * clearing of the background.
  353.      *
  354.      * @param g the graphics context
  355.      * @see java.awt.Component#repaint
  356.      * @see #paint
  357.      */
  358.     public void update(Graphics g)
  359.     {
  360.         paint(g);
  361.     }
  362.  
  363.     /**
  364.      * Draws plasma data into an internal buffer.  Not generally called directly.
  365.      */
  366.     public void drawplasma()
  367.     {
  368.         int i;
  369.         int j;
  370.         char t1;
  371.         char t2;
  372.         char t3;
  373.         char t4;
  374.         t3 = (char) (y1);
  375.         t4 = (char) (y2);
  376.  
  377.         for(j = 0; j < dim.height * dim.width; j += dim.width + dim.width + dim.width)
  378.         {
  379.             t1 = (char) (x1);
  380.             t2 = (char) (x2);
  381.  
  382.             for(i = 0; i < dim.width; i += 4)
  383.             {
  384.                 buffer[i + j]              = (byte) ((costab[t1 & 255] +
  385.                                                       costab[t2 & 255] +
  386.                                                       costab[t3 & 255] +
  387.                                                       costab[t4 & 255]));
  388.  
  389.                 buffer[i + j + 1]         = buffer[i + j];
  390.                 buffer[i + j + 2]         = buffer[i + j];
  391.                 buffer[i + j + 3]         = buffer[i + j];
  392.                 buffer[i + j + dim.width]         = buffer[i + j];
  393.  
  394.                 buffer[i + j + dim.width + 1]     = buffer[i + j];
  395.                 buffer[i + j + dim.width + 2]     = buffer[i + j];
  396.                 buffer[i + j + dim.width + 3]     = buffer[i + j];
  397.                 buffer[i + j + dim.width + dim.width]     = buffer[i + j];
  398.  
  399.                 buffer[i + j + dim.width + dim.width + 1] = buffer[i + j];
  400.                 buffer[i + j + dim.width + dim.width + 2] = buffer[i + j];
  401.                 buffer[i + j + dim.width + dim.width + 3] = buffer[i + j];
  402.  
  403.                 t1 += x1mod;
  404.                 t2 += x2mod;
  405.             }
  406.  
  407.             t3 += y1mod;
  408.             t4 += y2mod;
  409.         }
  410.     }
  411.  
  412.     /**
  413.      * Moves Plasma occurance location at random within component.  Not generally called directly.
  414.      */
  415.     public void moveplasma()
  416.     {
  417.         x1 -= x1mod * 2;
  418.         y1 += y1mod * 2;
  419.         x1 += (byte) (Math.random() * 3);
  420.         x2 -= (byte) (Math.random() * 4);
  421.         y1 += (byte) (Math.random() * 3);
  422.         y2 -= (byte) (Math.random() * 5);
  423.  
  424.         //Null the image, so we recreate it
  425.         if (img!=null) img.flush();
  426.             img = null;
  427.     }
  428.  
  429.     /**
  430.      * Setup Plasma Palette.  Not generally called directly.
  431.      */
  432.     public void dopalette()
  433.     {
  434.         int i;
  435.  
  436.         for(i = 0; i < 32; i++)
  437.         {
  438.             red[i]   = (byte) 255;
  439.             green[i] = 0;
  440.             blue[i]  = (byte) (i*8);
  441.         }
  442.  
  443.         for(i = 32; i < 96; i++)
  444.         {
  445.             red[i]   = (byte) (255-(i*8));
  446.             green[i] = (byte) (i*8);
  447.             blue[i]  = (byte) 255;
  448.         }
  449.  
  450.         for(i = 64; i < 96; i++)
  451.         {
  452.             red[i]   = 0;
  453.             green[i] = (byte) 255;
  454.             blue[i]  = (byte) (255-(i*8));
  455.         }
  456.  
  457.         for(i = 96; i < 128; i++)
  458.         {
  459.             red[i]   = (byte) (i*8);
  460.             green[i] = (byte) (255-(i*8));
  461.             blue[i]  = 0;
  462.         }
  463.     }
  464.  
  465.     /**
  466.      * Setup Plasma cosine table.  Not generally called directly.
  467.      */
  468.     public void setupcos()
  469.     {
  470.         int i;
  471.  
  472.         for(i = 0; i < 256; i++)
  473.         {
  474.             costab[i]=(byte) (16 + Math.cos(((double)i * 360 / 255 / 180) *Math.PI) * 15);
  475.         }
  476.     }
  477.  
  478.     private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
  479.         in.defaultReadObject();
  480.  
  481.         cModel = new IndexColorModel(7, 128, red, green, blue);
  482.     }
  483.  
  484. }
  485.